#include <Arduino.h>
#include "WiFi.h"
#include "common.h"


#define QUEUE_ITEM_NUM  300
#define DATA_BUF_SIZE 100

#define WIFI_SSID       "ESP32_UART"
#define WIFI_PASSWORD   "1234567890"

#define ACTIVE_TIMEOUT 60

time_t last_recv_time = 0;

class Data
{
public:
    uint32_t len;
    uint8_t buf[DATA_BUF_SIZE];
};

static xQueueHandle xQueueSerial=NULL;
static xQueueHandle xQueueTCP=NULL;

WiFiServer server;
WiFiUDP udp;
int timeout = 0;

static TaskHandle_t xSerialTask = NULL;

void serial_on_receive(void)
{
    Data data;
    int bytes_to_read = 0;
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    while(Serial.available())
    {
        bytes_to_read = Serial.available();
        if(bytes_to_read > 0)
        {
            if(bytes_to_read > DATA_BUF_SIZE)
            {
                bytes_to_read = DATA_BUF_SIZE;
            }

            data.len = Serial.read(data.buf,bytes_to_read);
            if(data.len)
            {
                xQueueSendFromISR(xQueueSerial,&data,&xHigherPriorityTaskWoken);
            }
        }
    }
}

void serial_task(void * args)
{
    Data data;

    Serial.onReceive(serial_on_receive, false); 

    for(;;)
    {
        if(xQueueReceive(xQueueTCP,&data,10)==pdPASS)
        {
            Serial.write(data.buf,data.len);
        }        
    }
}

static TaskHandle_t xTcpTask = NULL;
void tcp_task(void * args)
{
    Data data;
    char str[DATA_BUF_SIZE * 2];
    int str_len=0;
    int bytes_to_read = 0;
    int led_delay=0;

    for(;;)
    {
        if(millis()%1000 == 0)
        {
            led_control(0);
        }
        if(millis()%1000 == 500)
        {
            led_control(1);
        }

        WiFiClient client = server.available(); //尝试建立客户对象
        if (client) //如果当前客户可用
        {
            led_control(1);
            timeout = 0;

            while (client.connected()) //如果客户端处于连接状态
            {
                bytes_to_read = client.available();
                if (bytes_to_read) //如果有可读数据
                {
                    led_control(0);
                    led_delay = 100;
                    if(bytes_to_read > DATA_BUF_SIZE)
                    {
                        bytes_to_read = DATA_BUF_SIZE;
                    }

                    data.len = client.read(data.buf,bytes_to_read);
                    if(data.len>0)
                    {
                        xQueueSend(xQueueTCP,&data,0);    
                    }
                }
                else
                {
                    if(xQueueReceive(xQueueSerial,&data,2)==pdPASS)
                    {                    
                        client.write(data.buf,data.len);                                      
                    }

                    if(led_delay>0)
                    {
                        led_delay--;
                    }
                    else
                    {
                        led_control(1);
                    }
                }

                if(timeout >= 10)
                {
                    break;
                }
            }
            client.stop(); //结束当前连接:
            led_control(0);
        }
    }
}

/***************************************************************************/

void WiFiEvent(WiFiEvent_t event) {
  switch (event) {
    case SYSTEM_EVENT_AP_START:
      Serial.println("WiFi AP Started");
      break;
    case SYSTEM_EVENT_AP_STOP:
      Serial.println("WiFi AP Stopped");
      break;
    case SYSTEM_EVENT_AP_STACONNECTED:
      Serial.println("Station Connected");
      break;
    case SYSTEM_EVENT_AP_STADISCONNECTED:
      Serial.println("Station Disconnected");
      break;
    default:
      break;
  }
}

/**
 * @brief 
 * 
 */
void setup()
{
    Serial.begin(115200);
    Serial.print("Mac:");
    Serial.println(WiFi.macAddress());

    led_init();

    Serial.println("AP_ENABLE");

    delay(1000);
    
    WiFi.onEvent(WiFiEvent, ARDUINO_EVENT_MAX);
    WiFi.softAP(WIFI_SSID, WIFI_PASSWORD);

    delay(1000);

    Serial.println("IP address: ");
    Serial.println(WiFi.softAPIP());

    server.begin(8000);  
    udp.begin(8001);

    xQueueSerial = xQueueCreate(QUEUE_ITEM_NUM,sizeof(Data));
    xQueueTCP = xQueueCreate(QUEUE_ITEM_NUM,sizeof(Data));

    xTaskCreatePinnedToCore(serial_task, "serial_task", 8192, NULL, 10, &xSerialTask, 0);
    xTaskCreatePinnedToCore(tcp_task, "tcp_task", 8192, NULL, 10, &xTcpTask, 1);
}

/**
 * @brief 
 * 
 */
void loop()
{
    uint8_t buf[100];

    int packetSize = udp.parsePacket();
    if (packetSize) 
    {
        int len = udp.read(buf, 100);
        if (len > 0) 
        {
            buf[len] = 0; // 为字符串添加结束符
        }
        //Serial.printf("UDP recv: %s\r\n", buf);

        udp.beginPacket(udp.remoteIP(), udp.remotePort());
        String str = "OK";
        udp.print(str);
        udp.endPacket();

        timeout = 0;
    }

    if(timeout <= 100)
    {
        timeout++;
    }
    delay(100);
}



